import { PlusOutlined } from '@ant-design/icons'
import { type OptionalFields, type RequiredFields, truthy } from '@gnlab/utils'
import { Form, Button, Input, message, Radio } from 'antd'
import { ImportantEditModal } from '@/desktop/components'
import services from '@/services'
import { formatChatFlowTaskTime } from '@/services/features/chat-flows'
import type { ChatFlow, ChatFlowTask } from '@/services/features/chat-flows'
import EditTask from './EditTask'
import './EditFlow.module.less'

type EditingFlow = OptionalFields<ChatFlow, 'id'>

export default function EditFlow(props: {
  flow: false | null | ChatFlow // false: 未进行编辑，null: 新增，ChatFlow: 修改
  onFinish: () => void
}) {
  const { flow, onFinish } = props

  const title = truthy(flow) ? '编辑工作流' : '新建工作流'

  return <ImportantEditModal
    title={title}
    open={flow !== false}
    onCancel={onFinish}
    width="700px"
    styleName="modal"
  >
    {flow !== false ? <Content flow={flow} onFinish={onFinish} /> : null}
  </ImportantEditModal>
}

function Content(props: { flow: null | ChatFlow; onFinish: () => void }) {
  const { flow, onFinish } = props

  const editing = truthy(flow)

  const initialFlow = useMemo<EditingFlow>(
    () => (flow ? { ...flow } : { name: '', forGroup: false, unsubscribeKeyword: '', tasks: [] }),
    [flow],
  )

  const [submitting, setSubmitting] = useState(false)
  const submit = useCallback(
    async (values: EditingFlow) => {
      setSubmitting(true)
      const res = await services.features.chatFlows.addOrUpdate({
        id: flow?.id,
        ...values,
      })
      setSubmitting(false)
      if (res.success) {
        void message.success('保存成功！')
        onFinish()
      } else {
        void message.success(`保存失败：${res.error}`)
      }
    },
    [flow, onFinish],
  )

  return <Form initialValues={initialFlow} onFinish={submit} labelCol={{ span: 5 }}>
    <main>
      <Form.Item label="工作流名称" name="name" rules={[{ required: true }]}>
        <Input />
      </Form.Item>

      <Form.Item label="工作流类型" name="forGroup" rules={[{ required: true }]}>
        <Radio.Group disabled={editing}>
          <Radio value={false}>私聊</Radio>
          <Radio value={true}>群聊</Radio>
        </Radio.Group>
      </Form.Item>

      <Form.Item dependencies={['forGroup']} noStyle>
        {({ getFieldValue }) => {
          const forGroup = getFieldValue('forGroup') as boolean
          return <Form.Item
            label="退订关键词"
            name="unsubscribeKeyword"
            rules={[{ required: !forGroup }]}
            extra="当用户发送此关键词后，将被加入工作流黑名单。本工作流将不再对该用户执行。用户不会收到后续的工作流消息。关键词匹配为精确匹配。"
            hidden={forGroup}
          >
            <Input />
          </Form.Item>
        }}
      </Form.Item>

      <Form.Item
        label="工作流"
        name="tasks"
        rules={[{ type: 'array', required: true, message: '必须设置发送内容' }]}
      >
        <TasksInput />
      </Form.Item>
    </main>
    <footer>
      <Button onClick={onFinish}>取消</Button>
      <Button type="primary" htmlType="submit" loading={submitting}>
        保存
      </Button>
    </footer>
  </Form>
}

function TasksInput(props: {
  value?: ChatFlow['tasks']
  onChange?: (value: ChatFlow['tasks']) => void
}) {
  const { value: tasks, onChange } = props as RequiredFields<typeof props, 'value' | 'onChange'>

  const maxDay = useMemo(() => (tasks.length ? Math.max(...tasks.map(v => v.day)) : 0), [tasks])

  const [editing, setEditing] = useState<false | null | { index: number; task: ChatFlowTask }>(
    false,
  )
  const editFinish = useCallback(
    (task: ChatFlowTask | null) => {
      if (editing === false) return
      if (task) {
        const updated = [...tasks]
        if (editing !== null) updated.splice(editing.index, 1)
        updated.push(task)
        updated.sort(
          (a, b) =>
            a.day * 24 * 60 + a.hour * 60 + a.minute - (b.day * 24 * 60 + b.hour * 60 + b.minute),
        )
        onChange(updated)
      }
      setEditing(false)
    },
    [tasks, editing, onChange],
  )

  const removeTask = useCallback(
    (index: number) => {
      const updated = [...tasks]
      updated.splice(index, 1)
      onChange(updated)
    },
    [tasks, onChange],
  )

  return <div styleName="edit-tasks">
    <Button
      icon={<PlusOutlined />}
      type="link"
      styleName="add-task"
      onClick={() => setEditing(null)}
    >
      添加工作流项目
    </Button>

    <div styleName="tasks">
      {tasks.map((task, index) => <div key={index} styleName="task">
        <div styleName="info">
          第{task.day}日<span styleName="time">{formatChatFlowTaskTime(task)}</span>执行
        </div>
        <div>
          <Button type="link" onClick={() => setEditing({ index, task })}>
            编辑
          </Button>
          <Button type="link" danger onClick={() => removeTask(index)}>
            删除
          </Button>
        </div>
      </div>)}
    </div>

    <EditTask
      task={truthy(editing) ? editing.task : editing}
      maxDay={maxDay}
      onFinish={editFinish}
    />
  </div>
}
